package com.lam.generator.common.util;

import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.RegExUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lam.common.base.domain.tree.BaseTree;
import com.lam.common.config.AppBaseConfig;
import com.lam.common.exception.BaseException;
import com.lam.common.exception.ParameterErrorException;
import com.lam.common.utils.BeanUtil;
import com.lam.common.utils.CollectionUtil;
import com.lam.common.utils.JsonUtil;
import com.lam.common.utils.StringUtils;
import com.lam.generator.common.config.GenConfig;
import com.lam.generator.common.constant.GeneratorConstant;
import com.lam.generator.entity.GenCodeModule;
import com.lam.generator.entity.GenTable;
import com.lam.generator.entity.GenTableColumn;
import com.lam.generator.entity.GenTableExtConfig;

/**
 * 代码生成器 工具类
 * 
 * @author lam
 */
public class GenUtils {
	
	private static final Logger logger = LoggerFactory.getLogger(GenUtils.class);
	
	public static Class<?> loadClass(String className) {
		try {
			if(StringUtils.isBlank(className)) {
				logger.error("类全名为空！");
				return null;
			}
			className = className.replaceAll("\\s", "");
			Class<?> clazz = Class.forName(className);
			if(clazz.isInterface()) {
				throw new ParameterErrorException("父类不支持接口");
			}
			logger.info("检查类可使用：{}", className);
			return clazz;
		} catch (ClassNotFoundException e) {
			logger.error("检查类未找到类文件：{}", className);
			return null;
		}
	}
	
	public static void setCodeModule(GenTable genTable, GenCodeModule codeModule) {
		genTable.setCodeModuleId(codeModule.getId());
		String tableName = genTable.getTableName();
		String tablePrefix = matchTablePrefix(codeModule, tableName);
		genTable.setClassName(StringUtils.toCamelCaseWithUpFirst(GenConfig.getAutoRemovePre()?StringUtils.replace(tableName, tablePrefix, ""):tableName));
		if(StringUtils.isBlank(genTable.getBusinessName())) {
			genTable.setBusinessName(StringUtils.toCamelCase(StringUtils.replace(tableName, tablePrefix, "")));
		}
		if(StringUtils.isBlank(genTable.getFunctionName())) {
			genTable.setFunctionName(RegExUtils.replaceAll(genTable.getTableComment(), "(?:表)", ""));
		}
	}
	
	/**
	 * 初始化表信息
	 */
	public static void initTable(GenTable genTable, GenCodeModule codeModule, String operName) {
		
		setCodeModule(genTable, codeModule);
		genTable.setFunctionAuthor(operName);
		genTable.setFunctionList(GenConfig.getFunctionList());
		genTable.setGenType("1");
		genTable.setTemplateType(GeneratorConstant.TEMP_TYPE_SIMPLE);
		genTable.setCreateBy(operName);
		genTable.setCreateTime(new Date());
		
		Map<String, Object> options = new HashMap<String, Object>();
		if(genTable.isSimpleTree()) {
			if(StringUtils.isBlank(genTable.getParentClassName())) {
				genTable.setParentClass(BaseTree.class);
				genTable.setParentClassName(BaseTree.class.getName());
			}
			options.put(GeneratorConstant.TREE_CODE, "id");
			options.put(GeneratorConstant.TREE_PARENT_CODE, "parent_id");
			options.put(GeneratorConstant.TREE_NAME, "");
		}
		
		if((genTable.hasFuncInsert() || genTable.hasFuncUpdate() || genTable.hasFuncImport())&& genTable.hasFuncUnique()) {
			options.put(GeneratorConstant.TABLE_UNIQUE_FIELD, "");
			options.put(GeneratorConstant.TABLE_UNIQUE_QUERY_FIELD, "id");
			options.put(GeneratorConstant.TABLE_UNIQUE_CONDITION_FIELD, "");
		}
		genTable.setOptions(JsonUtil.toJsonString(options));
	}
	
	public static String matchTablePrefix(GenCodeModule codeModule, String tableName) {
		String tablePrefix = codeModule.getTablePrefix();
    	if(StringUtils.isBlank(tableName) || StringUtils.isBlank(tablePrefix)) {
    		return null;
    	}
    	tableName = tableName.toLowerCase();
    	if(!tablePrefix.contains(",")) {
    		return tableName.startsWith(tablePrefix.toLowerCase())?tablePrefix:null;
    	}
    	
    	String[] ss = tablePrefix.split(",");
    	for (String s : ss) {
			if(tableName.startsWith(s.toLowerCase())) {
				return s;
			}
		}
    	return null;
    }
	
	public static GenCodeModule mergeTableExtConfig(GenCodeModule codeModule, GenTableExtConfig tableExtConfig) {
		if(codeModule == null) {
			return codeModule;
		}
		//清除无关信息
		codeModule.setId(null);
		codeModule.setCreateBy(null);
		codeModule.setCreateTime(null);
		codeModule.setUpdateBy(null);
		codeModule.setUpdateTime(null);
		codeModule.setStatus(null);
		codeModule.setRemark(null);
		if(tableExtConfig == null) {
			return codeModule;
		}
		if(StringUtils.isNotEmpty(tableExtConfig.getModuleShort())) {
			codeModule.setModuleShort(tableExtConfig.getModuleShort());
		}
		if(StringUtils.isNotEmpty(tableExtConfig.getPackageName())) {
			codeModule.setPackageName(tableExtConfig.getPackageName());
		}
		if(StringUtils.isNotEmpty(tableExtConfig.getUiPath())) {
			codeModule.setUiPath(tableExtConfig.getUiPath());
		}
		return codeModule;
	}
	
	public static GenTableExtConfig diffTableExtConfig(GenCodeModule codeModule, GenTableExtConfig tableExtConfig) {
		if(codeModule == null || tableExtConfig == null) {
			return tableExtConfig;
		}
		if(StringUtils.equals(tableExtConfig.getModuleShort(), codeModule.getModuleShort())) {
			tableExtConfig.setModuleShort("");
		}
		if(StringUtils.equals(tableExtConfig.getPackageName(), codeModule.getPackageName())) {
			tableExtConfig.setPackageName("");
		}
		if(StringUtils.equals(tableExtConfig.getUiPath(), codeModule.getUiPath())) {
			tableExtConfig.setUiPath("");
		}
		return tableExtConfig;
	}
	
	/**
	 * 初始化列属性字段
	 */
	public static GenTableColumn initColumnField(GenTableColumn column, GenTable table) {

		column.setTableId(table.getId());
		column.setCreateBy(table.getCreateBy());
//		if(column.getColumnLength() == null) {
//			column.setColumnLength(getColumnLength(column.getColumnType()));
//		}
		String columnName = column.getColumnName();
		
		// 设置java字段信息
		column.setJavaLength(column.getColumnLength());
		column.setJavaField(StringUtils.toCamelCase(columnName));
		column.setJavaFieldDesc(column.convertDesc());
		column.setFormItemLabel(column.getJavaFieldDesc());

		String dataType = getDbType(column.getColumnType());
		if (CollectionUtil.contains(GeneratorConstant.COLUMNTYPE_STR, dataType)) {
			//字符串类型
			column.setJavaType(GeneratorConstant.TYPE_STRING);
			// 字符串长度超过200设置为文本域
			column.setHtmlType(column.getColumnLength() >= 200 ? GeneratorConstant.HTML_TEXTAREA : GeneratorConstant.HTML_INPUT);

		} else if (CollectionUtil.contains(GeneratorConstant.COLUMNTYPE_TIME, dataType)) {
			//时间类型
			column.setJavaType(GeneratorConstant.TYPE_DATE);
			column.setHtmlType(GeneratorConstant.HTML_DATETIME);

		} else if (CollectionUtil.contains(GeneratorConstant.COLUMNTYPE_DATE, dataType)) {
			//日期类型
			column.setJavaType(GeneratorConstant.TYPE_STRING);
			column.setHtmlType(GeneratorConstant.HTML_DATE);

		} else if (CollectionUtil.contains(GeneratorConstant.COLUMNTYPE_NUMBER, dataType)) {
			//数字类型
			column.setHtmlType(GeneratorConstant.HTML_INPUT_NUMBER);
			// 如果是浮点型 统一用BigDecimal
			String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
			if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) {
				column.setJavaType(GeneratorConstant.TYPE_BIGDECIMAL);
			} else if (CollectionUtil.contains(GeneratorConstant.COLUMNTYPE_LONG_NUMBER, dataType)) {
				column.setJavaType(GeneratorConstant.TYPE_LONG);// 长整形
			} else {
				column.setJavaType(GeneratorConstant.TYPE_INTEGER);
			}
		}

		if (!CollectionUtil.contains(GeneratorConstant.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk()) {
			// 编辑字段
			column.setIsEdit(GeneratorConstant.REQUIRE);
		}
		// 列表字段
		if (!CollectionUtil.contains(GeneratorConstant.COLUMNNAME_NOT_LIST, columnName) && !column.isPk()) {
			column.setIsList(GeneratorConstant.REQUIRE);
		}
		// 查询字段
		if (isQueryField(column)) {
			column.setIsQuery(GeneratorConstant.REQUIRE);
		}

		// 查询字段类型
		if (StringUtils.endsWithIgnoreCase(columnName, "name")) {
			column.setQueryType(GeneratorConstant.QUERY_LIKE);
			column.setIsQuery(GeneratorConstant.REQUIRE);
		}
		// 状态字段设置单选框
		if (StringUtils.endsWithIgnoreCase(columnName, "status")) {
			column.setHtmlType(GeneratorConstant.HTML_RADIO);

		} else if (StringUtils.endsWithIgnoreCase(columnName, "sex")) {
			// 性别字段设置下拉框
			column.setHtmlType(GeneratorConstant.HTML_SELECT);
		}

		String dictText = column.readConverterExp();
		if (StringUtils.isNotBlank(dictText)) {
			column.setDictText(column.getColumnName() + "_type " + dictText);
			column.setHtmlType(GeneratorConstant.HTML_SELECT);
		}
		
		return column;
	}

	private static boolean isQueryField(GenTableColumn column) {
		if (CollectionUtil.contains(GeneratorConstant.COLUMNNAME_NOT_QUERY, column.getColumnName()) || column.isPk()
				|| CollectionUtil.contains(GeneratorConstant.JAVA_TYPE_NOT_QUERY, column.getJavaType())) {
			return false;
		}

		return StringUtils.equalsAnyIgnoreCase(column.getJavaType(), "int", "Integer", "short")
				&& !StringUtils.containsAny(column.getColumnType(), "char", "integer", "int", "tinyint", "smallint");
	}
	
	public static void parseParentClass(GenTable genTable) {
		if(StringUtils.isBlank(genTable.getParentClassName())) {
			genTable.setParentFieldList(Collections.emptyList());
			return ;
		}
		Class<?> clazz = loadClass(genTable.getParentClassName());
		if(clazz == null) {
			logger.error("未找到父类Java文件:{}", genTable.getParentClassName());
			throw new BaseException("未找到父类Java文件");
		}
		genTable.setParentClass(clazz);
		genTable.setParentFieldList(BeanUtil.getFieldNames(clazz));
	}

	/**
	 * 设置主键列信息
	 * 
	 * @param genTable   业务表信息
	 * @param columns 业务字段列表
	 */
	public static void setPkColumn(GenTable genTable) {
		List<String> parentFieldList = genTable.getParentFieldList();
		for (GenTableColumn column : genTable.getColumns()) {
			if (column.isPk()) {
				genTable.setPkColumn(column);
			}
			column.setSuperColumn(parentFieldList.contains(column.getJavaField()));
		}
		if (genTable.getPkColumn() == null) {
			genTable.setPkColumn(genTable.getColumns().get(0));
		}
	}

	/**
	 * 获取代码文件基础路径
	 * @param table    业务表信息
	 * @param template 模板文件路径
	 * @return 基础路径
	 */
	public static String getGenBasePath(String genPath) {
		
		if (StringUtils.isBlank(genPath) || StringUtils.equals(genPath, "/")) {
			genPath = System.getProperty("user.dir").replace(AppBaseConfig.me().getJavaStarterName(), "")
					.replace(AppBaseConfig.me().getJavaProjectName(), "")
					.replace("\\\\", "\\");
		}
		return genPath;
	}

	/**
	 * 获取数据库类型字段
	 * 
	 * @param columnType 列类型
	 * @return 截取后的列类型
	 */
	public static String getDbType(String columnType) {
		if (StringUtils.indexOf(columnType, "(") > 0) {
			return StringUtils.substringBefore(columnType, "(");
		} else {
			return columnType;
		}
	}

}
